#include "camera_class.h"

camera::camera()
{
    nRet = MV_OK;
    handle = NULL;
    g_bExit = false;
    g_nPayloadSize = 0;
    pDataForRGB = (unsigned char *)malloc(1280 * 768 * 4 + 2048);
    // memset(&stParam, 1, sizeof(MVCC_INTVALUE));
    memset(&stParam, 0, sizeof(MVCC_INTVALUE));
    CvtParam = {0};
    stOutFrame = {0};
    // memset(&stOutFrame, 1, sizeof(MV_FRAME_OUT));
    memset(&stOutFrame, 0, sizeof(MV_FRAME_OUT));
}

void camera::start_cam()
{

    memset(&stDeviceList, 1, sizeof(MV_CC_DEVICE_INFO_LIST));
    // memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
    nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);
    if (0 < stDeviceList.nDeviceNum)
    {
        for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++)
        {
            pDeviceInfo = stDeviceList.pDeviceInfo[i];
            if (NULL == pDeviceInfo)
            {
                break;
            }
            PrintDeviceInfo();
        }
    }
    else
    {
        std::cout << "Find no Device" << std::endl;
    }
    unsigned int nIndex = 0;
    MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
    // 打开相机设备
    MV_CC_OpenDevice(handle);
    // 新增：查询相机支持的Width范围
    MVCC_INTVALUE stWidthRange;
    nRet = MV_CC_GetIntValue(handle, "Width", &stWidthRange);
    if (MV_OK == nRet)
    {
        std::cout << "相机支持的Width范围："
                  << "最小=" << stWidthRange.nMin << ", "
                  << "最大=" << stWidthRange.nMax << ", "
                  << "步长=" << stWidthRange.nInc << std::endl;
    }
    else
    {
        std::cerr << "查询Width范围失败，错误码：" << nRet << std::endl;
    }

    // 新增：查询相机支持的Height范围
    MVCC_INTVALUE stHeightRange;
    nRet = MV_CC_GetIntValue(handle, "Height", &stHeightRange);
    if (MV_OK == nRet)
    {
        std::cout << "相机支持的Height范围："
                  << "最小=" << stHeightRange.nMin << ", "
                  << "最大=" << stHeightRange.nMax << ", "
                  << "步长=" << stHeightRange.nInc << std::endl;
    }
    else
    {
        std::cerr << "查询Height范围失败，错误码：" << nRet << std::endl;
    }

    int target_width = 1280;                                 // 目标宽度
    int target_height = 768;                                // 目标高度
    nRet = MV_CC_SetIntValue(handle, "Width", target_width); // 设置宽度
    if (MV_OK != nRet)
    {
        std::cout << "设置宽度 " << target_width << " 失败！错误码：" << nRet << std::endl;
        return; // 若失败，说明相机不支持该分辨率，需换其他4:3分辨率
    }
    // 设置高度
    nRet = MV_CC_SetIntValue(handle, "Height", target_height);
    if (MV_OK != nRet)
    {
        std::cout << "设置高度 " << target_height << " 失败！错误码：" << nRet << std::endl;
        return;
    }
    // cout << "相机分辨率已显式设置为：1280×960（4:3比例）" << endl;
    if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
    {
        int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
        if (0 < nPacketSize)
        {
            MV_CC_SetIntValue(handle, "GevSCPSPacketSize", nPacketSize);
        }
        else
        {
            std::cout << "Warning: Get Packet Size fail" << std::endl;
        }
    }
    MVCC_ENUMVALUE p = {0};
    MVCC_STRINGVALUE st;
    MV_CC_GetStringValue(handle, "DeviceModelName", &st);
    std::cout << "DeviceModelName: " << st.chCurValue << std::endl;
    MV_CC_GetStringValue(handle, "DeviceVersion", &st);
    std::cout << "DeviceVersion:\t" << st.chCurValue << std::endl;
    MV_CC_GetEnumValue(handle, "DeviceScanType", &p);
    if (0 == p.nCurValue)
    {
        std::cout << "DeviceScanType:\t" << "Areascan" << std::endl;
    }
    else
    {
        std::cout << "DeviceScanType:\t" << "Linescan" << std::endl;
    }

    MV_CC_SetEnumValue(handle, "ExposureAuto", 0);     // 关闭自动曝光
    MV_CC_SetEnumValue(handle, "GainAuto", 0);         // 关闭自动增益
    MV_CC_SetEnumValue(handle, "BalanceWhiteAuto", 0); // 关闭自动白平衡
    // 设置固定的曝光时间
    MV_CC_SetFloatValue(handle, "ExposureTime", 30000.0f); // 8000微秒，根据实际情况调整
    // 设置固定的增益
    MV_CC_SetFloatValue(handle, "Gain", 5.0f);
    // 设置像素格式为BayerRG8
    MV_CC_SetEnumValue(handle, "PixelFormat", 0x01080008);  // BayerRG8
    // 设置触发模式为连续采集
    MV_CC_SetEnumValue(handle, "TriggerMode", 0); // 触发模式关闭，连续采集

    // 设置数据包大小优化
    if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE)
    {
        int nPacketSize = MV_CC_GetOptimalPacketSize(handle);
        if (0 < nPacketSize)
        {
            MV_CC_SetIntValue(handle, "GevSCPSPacketSize", nPacketSize);
        }
        else
        {
            std::cout << "Warning: Get Packet Size fail" << std::endl;
        }
    }

    MV_CC_GetIntValue(handle, "PayloadSize", &stParam); // 获取各种图像参数，比如宽度、高度
    g_nPayloadSize = stParam.nCurValue;
    nRet = MV_CC_StartGrabbing(handle);
    if (MV_OK == nRet)
        std::cout << "Start Grabbing !" << std::endl;
    std::cout << "\nPress ESC to exit.\n";
}

void camera::PrintDeviceInfo()
{
    if (NULL == pDeviceInfo)
    {
        std::cout << "null point" << std::endl;
    }
    if (pDeviceInfo->nTLayerType == MV_GIGE_DEVICE)
    {
        int nIp1 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24);
        int nIp2 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16);
        int nIp3 = ((pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8);
        int nIp4 = (pDeviceInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);
        std::cout << "IP:" << nIp1 << "." << nIp2 << "." << nIp3 << "." << nIp4 << std::endl;
    }
}

void camera::close_cam()
{
    int nRet = MV_CC_StopGrabbing(handle);
    if (MV_OK == nRet)
    {
        std::cout << "Stopped Grabbing !" << std::endl;
    }
}

void camera::get_pic(cv::Mat *srcimg)
{
    MV_CC_GetImageBuffer(handle, &stOutFrame, 100); // 超时时间从100ms减少到50ms
    if (nRet != MV_OK)
    {
        // 如果获取失败，直接返回空图像
        *srcimg = cv::Mat();
        return;
    }

    int actual_width = stOutFrame.stFrameInfo.nWidth;
    int actual_height = stOutFrame.stFrameInfo.nHeight;

    // 检查是否支持BayerRG8
    if (stOutFrame.stFrameInfo.enPixelType == PixelType_Gvsp_BayerRG8) 
    {
        // 直接使用Bayer数据创建Mat对象，避免内存拷贝
        static cv::Mat bayer_mat;
        bayer_mat = cv::Mat(stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth, 
                           CV_8UC1, stOutFrame.pBufAddr);
        
        // 预分配BGR图像内存
        static cv::Mat bgr_mat;
        if (bgr_mat.empty() || 
            bgr_mat.rows != stOutFrame.stFrameInfo.nHeight || 
            bgr_mat.cols != stOutFrame.stFrameInfo.nWidth) 
        {
            bgr_mat.create(stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth, CV_8UC3);
        }
        
        // 快速Bayer到BGR转换
        cv::cvtColor(bayer_mat, bgr_mat, cv::COLOR_BayerRG2BGR);
        *srcimg = bgr_mat;
        
    } 
    else
    {
        // 备用方案
        CvtParam.enSrcPixelType = stOutFrame.stFrameInfo.enPixelType;
        CvtParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed;
        CvtParam.nHeight = stOutFrame.stFrameInfo.nHeight;
        CvtParam.nWidth = stOutFrame.stFrameInfo.nWidth;
        CvtParam.nDstBufferSize = stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 3 + 2048;
        CvtParam.pSrcData = stOutFrame.pBufAddr;
        CvtParam.pDstBuffer = pDataForRGB;
        CvtParam.nSrcDataLen = stOutFrame.stFrameInfo.nFrameLen;
        
        MV_CC_ConvertPixelType(handle, &CvtParam);
        *srcimg = cv::Mat(stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth, 
                         CV_8UC3, pDataForRGB);
    }


    if (NULL != stOutFrame.pBufAddr)
    {
        MV_CC_FreeImageBuffer(handle, &stOutFrame);
    }
}

float camera::calculateBrightness(cv::Mat& frame)
{
    if (frame.empty()) return 0.0f;
    
    cv::Mat gray;
    if (frame.channels() == 3) {
        cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
    } else {
        gray = frame;
    }
    
    cv::Scalar mean = cv::mean(gray);
    return mean[0];
}

void camera::adaptiveExposureControl(cv::Mat& frame)
{
    if (frame.empty()) return;
    
    // 计算当前帧亮度
    float brightness = calculateBrightness(frame);
    
    // 更新亮度历史
    brightness_history[brightness_index] = brightness;
    brightness_index = (brightness_index + 1) % 10;
    
    // 每10帧调整一次参数
    adaptive_counter++;
    if (adaptive_counter % 10 == 0) 
    {
        // 计算平均亮度
        float avg_brightness = 0;
        for (int i = 0; i < 10; i++) 
        {
            avg_brightness += brightness_history[i];
        }
        avg_brightness /= 10.0f;
        
        // 调整曝光和增益
        if (avg_brightness < 80) 
        { // 太暗
            current_exposure = std::min(current_exposure * 1.2f, 20000.0f);
            current_gain = std::min(current_gain + 1.0f, 12.0f);
        } 
        else if (avg_brightness > 180) 
        { // 太亮
            current_exposure = std::max(current_exposure * 0.8f, 1000.0f);
            current_gain = std::max(current_gain - 1.0f, 0.0f);
        }
        
        // 应用新的相机参数
        MV_CC_SetFloatValue(handle, "ExposureTime", current_exposure);
        MV_CC_SetFloatValue(handle, "Gain", current_gain);
        
        std::cout << "自适应调整: 亮度=" << avg_brightness 
                  << ", 曝光=" << current_exposure 
                  << ", 增益=" << current_gain << std::endl;
    }
}

void camera::optimizeForDetection()
{
    // 专门为检测优化的参数设置
    MV_CC_SetFloatValue(handle, "Gamma", 1.0f);           // 关闭Gamma校正或设为1.0
    MV_CC_SetBoolValue(handle, "GammaEnable", 0);         // 禁用Gamma
    
    // 锐化设置（如果支持）
    MV_CC_SetEnumValue(handle, "SharpnessEnable", 1);     
    MV_CC_SetFloatValue(handle, "Sharpness", 1.5f);     
    
    // 降噪设置（如果支持）
    MV_CC_SetEnumValue(handle, "NoiseReduction", 1);     
    
    // 设置合适的曝光时间范围
    MV_CC_SetFloatValue(handle, "AutoExposureTimeLowerLimit", 1000.0f);   // 最小曝光1ms
    MV_CC_SetFloatValue(handle, "AutoExposureTimeUpperLimit", 30000.0f);  // 最大曝光30ms
    
    // 设置合适的增益范围
    MV_CC_SetFloatValue(handle, "AutoGainLowerLimit", 1.0f);              // 最小增益0dB
    MV_CC_SetFloatValue(handle, "AutoGainUpperLimit", 9.0f);             // 最大增益12dB
    
    std::cout << "相机已优化为检测模式" << std::endl;
}

// void camera::start_continuous_capture()
// {
//     if (m_running) return;
    
//     m_running = true;
//     m_capture_thread = std::thread(&camera::capture_loop, this);
//     std::cout << "开始连续图像捕获" << std::endl;
// }

// void camera::stop_continuous_capture()
// {
//     m_running = false;
//     if (m_capture_thread.joinable()) 
//     {
//         m_capture_thread.join();
//     }
//     std::cout << "停止连续图像捕获" << std::endl;
// }

// void camera::capture_loop()
// {
//     cv::Mat frame;
//     int frame_count = 0;
//     auto start_time = std::chrono::high_resolution_clock::now();
    
//     while (m_running) {
//         auto capture_start = std::chrono::high_resolution_clock::now();
        
//         get_pic(&frame);
        
//         if (!frame.empty()) {
//             std::lock_guard<std::mutex> lock(g_frame_mutex);
//             g_thread_data.frame = frame.clone();
//             g_thread_data.frame_ready = true;
//             g_frame_cv.notify_one();
//         }
        
//         // 计算捕获帧率
//         frame_count++;
//         auto current_time = std::chrono::high_resolution_clock::now();
//         std::chrono::duration<double> elapsed = current_time - start_time;
//         if (elapsed.count() >= 1.0) {
//             g_capture_fps = frame_count;
//             frame_count = 0;
//             start_time = current_time;
//         }
        
//         // 短暂休息，避免过度占用CPU
//         std::this_thread::sleep_for(std::chrono::milliseconds(1));
//     }
// }

// bool camera::get_latest_frame(cv::Mat& frame)
// {
//     std::lock_guard<std::mutex> lock(g_frame_mutex);
//     if (!g_thread_data.frame.empty()) {
//         frame = g_thread_data.frame.clone();
//         return true;
//     }
//     return false;
// }
